import axios, { type AxiosRequestConfig, AxiosError } from "axios";

import { setLocalStorage, getLocalStorage } from "@/stores/localstorage";
import { BASE_URL, TIMEOUT, SOURCE_URL } from "../config";
import { ElMessage } from "element-plus";

import router from "../router";

import { v4 as uuidv4 } from "uuid";

// 创建axios实例
const instance = axios.create({
  baseURL: BASE_URL,
  timeout: TIMEOUT,

  // 请求头
  headers: {
    Accept: "application/json", // TODO 移除默认的Accept头，让每个请求单独设置
    "Content-Type": "application/json",
  },
});

// 生成或获取设备ID（持久化存储）
const getDeviceId = () => {
  let deviceId = localStorage.getItem("device_id");
  if (!deviceId) {
    deviceId = uuidv4();
    localStorage.setItem("device_id", deviceId); // todo: 持久化存储
  }
  return deviceId;
};

// 请求拦截器, 请求拦截器会在请求发送之前拦截请求
instance.interceptors.request.use(
  (config) => {
    // 统一添加设备ID（无论是否需要认证）
    config.headers["Device-Id"] = getDeviceId();

    // 设置语言
    config.headers.AcceptLanguage = getLocalStorage("locale") || "zh-CN";

    // 定义不需要token认证的请求路径
    const excludePaths = ["/user/login", "/user/register", "/captcha"];
    const shouldSkipAuth = excludePaths.some((path) =>
      config.url?.includes(path)
    );

    if (shouldSkipAuth) {
      return config;
    }

    // 需要认证的请求处理
    const token = localStorage.getItem("token") || "";
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    } else {
      router.push("/login");
      return Promise.reject(new Error("未认证,请先登录！"));
    }

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 响应拦截器
instance.interceptors.response.use(
  (response) => {
    return handleData(response);
  },
  (error) => {
    if (error.response) {
      const { status, data } = error.response;

      // 401 未授权，跳转到登录页
      if (status === 401) {
        localStorage.removeItem("token"); // 清除token
        localStorage.removeItem("role-isAdmin"); // 清除管理员
        localStorage.removeItem("userNo"); // 清除用户
        localStorage.removeItem("username"); // 清除用户名
        localStorage.removeItem("device_id"); // 清除设备ID

        ElMessage({
          message: "未授权，请先登录！",
          type: "error",
        });

        router.push("/login"); // 使用路由跳转，而不是直接修改 window.location
        return Promise.reject(error);
      }

      // 500 服务器错误，跳转到指定 URL
      if (data.code === 500) {
        window.location.href = SOURCE_URL;
        return Promise.reject(error);
      }

      // 其他错误，显示错误消息
      const err = data.message;
      if (err && err !== "" && err != null) {
        ElMessage({
          message: err,
          type: "error",
        });
      } else {
        ElMessage({
          message: "HTTP: 服务器遇到错误，请求失败。",
          type: "error",
        });
      }
    }
    return Promise.reject(error);
  }
);

// 封装 fetchWithAuth
export const fetchWithAuth = async (url: string, options: RequestInit = {}) => {
  const token = localStorage.getItem("token") || "";

  // 创建新的Headers对象，避免修改原始headers
  const headers = new Headers(options.headers || {});

  // 智能设置Content-Type
  if (!headers.has("Content-Type")) {
    // 如果是FormData，让浏览器自动设置Content-Type（包含boundary）
    if (options.body instanceof FormData) {
      // 不设置Content-Type，浏览器会自动处理
    } 
    // 其他情况默认使用application/json
    else {
      headers.set("Content-Type", "application/json");
    }
  }

  // 设置认证和其他固定headers
  headers.set("Authorization", `Bearer ${token}`);
  headers.set("Device-Id", getDeviceId());
  headers.set("AcceptLanguage", getLocalStorage("locale") || "zh-CN");

  // 创建新options对象
  const newOptions: RequestInit = {
    ...options,
    headers,
  };

  return fetch(url, newOptions);
};

// 流式请求方法封装 - 用户AI流式回答
// 修改postStream方法
const postStream = async (
  url: string,
  data: any,
  onProgress: (chunk: string) => void,
  config?: AxiosRequestConfig
) => {
  const mergedConfig = {
    ...config,
    responseType: "text", // 必须为text
    headers: {
      ...config?.headers,
      Accept: "text/html", // 匹配后端的produces
      "Content-Type": "application/json",
    },
    onDownloadProgress: (progressEvent: ProgressEvent) => {
      // 正确的获取方式
      const target = progressEvent.target as XMLHttpRequest;
      const chunk = target.responseText;
      onProgress(chunk);
    },
  };

  try {
    return await instance.post(url, data, mergedConfig);
  } catch (error) {
    return handleError(error);
  }
};

//API 封装
const get = async (url: string) => {
  try {
    return await instance.get(url);
  } catch (error) {
    return handleError(error);
  }
};

// 封装GET请求
export const getWithParams = async <T = any>(
  url: string,
  params?: any,
  config?: AxiosRequestConfig
): Promise<T> => {
  try {
    const response = await instance.get<T>(url, {
      ...config, // 先展开config
      params, // params直接放在这一层
    });
    return response.data;
  } catch (error) {
    return handleError(error as AxiosError);
  }
};

const post = async (
  url: string,
  data: any,
  config?: AxiosRequestConfig<any> | undefined
) => {
  try {
    return await instance.post(url, data, config);
  } catch (error) {
    return handleError(error);
  }
};

const deleteFn = async (
  url: string,
  config?: AxiosRequestConfig<any> | undefined
) => {
  try {
    return await instance.delete(url, config);
  } catch (error) {
    return handleError(error);
  }
};

const deleteWithData = async (
  url: string,
  data: any,
  config?: AxiosRequestConfig<any> | undefined
) => {
  try {
    return await instance.delete(url, {
      ...config, // 保留原有 config
      data, // 将 data 放入 config
    });
  } catch (error) {
    return handleError(error);
  }
};

const postJSON = async (
  url: string,
  data: any,
  config?: AxiosRequestConfig<any> | undefined
) => {
  data = JSON.stringify(data);
  try {
    return await instance.post(url, data, config);
  } catch (error) {
    return handleError(error);
  }
};

const patchFn = async (
  url: string,
  data: any,
  config?: AxiosRequestConfig<any> | undefined
) => {
  try {
    return await instance.patch(url, data, config);
  } catch (error) {
    return handleError(error);
  }
};

// PUT 请求方法封装
const put = async (
  url: string,
  data: any,
  config?: AxiosRequestConfig<any> | undefined
) => {
  try {
    return await instance.put(url, data, config);
  } catch (error) {
    return handleError(error);
  }
};

//对请求返回的错误进行自处理
function handleError(error: any) {
  return error;
}

//对响应的数据进行自处理
function handleData(data: any) {
  return data;
}

export default {
  get: get,
  getWithParams: getWithParams,
  post: post,
  delete: deleteFn,
  deleteWithData: deleteWithData,
  postJSON: postJSON,
  patch: patchFn,
  put: put, // put 请求方法
  postStream: postStream, // 新增流式请求方法
  fetchWithAuth: fetchWithAuth, // 新增fetchWithAuth方法
};
